package com.bruce.spring.http.client.factory;

import com.bruce.spring.http.client.monitor.JdkHttpClientMonitor;
import com.bruce.spring.http.client.util.SslUtil;
import io.netty.handler.ssl.JdkSslContext;
import io.netty.handler.ssl.SslContext;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.http.client.ReactorClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.support.RestClientAdapter;
import org.springframework.web.service.invoker.HttpExchangeAdapter;
import reactor.netty.http.HttpProtocol;

import javax.net.ssl.SSLContext;
import java.lang.reflect.Field;
import java.net.http.HttpClient;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;

/**
 * Created by bruce in 2025/6/29 02:20
 * 和 RestTemplateAdapterCreator 一样的代码
 */
@RequiredArgsConstructor
@Component
public class RestClientAdapterCreator implements HttpExchangeAdapterCreator {

    private final HttpMessageConverters messageConverters;
    private final JdkHttpClientMonitor jdkHttpClientMonitor;

    @Override
    public HttpExchangeAdapter useReactorNettyHttpClient(String url) {
        reactor.netty.http.client.HttpClient reactorHttpClient = reactor.netty.http.client.HttpClient.create()
                .protocol(HttpProtocol.H2C)
                .baseUrl(url);
        ReactorClientHttpRequestFactory clientFactory = new ReactorClientHttpRequestFactory(reactorHttpClient);

        RestClient restClient = RestClient.builder()
                .baseUrl(url)
                .requestFactory(clientFactory)
                .messageConverters(messageConverters.getConverters())
                .build();
        return RestClientAdapter.create(restClient);
    }

    @Override
    public HttpExchangeAdapter useJdk9HttpClient(String url) {

        java.net.http.HttpClient httpClient = null;
        try {
            SslContext sslContext = SslUtil.sslClientContext();
            //反射获取 ((JdkSslClientContext) sslContext).sslContext
            Field sslContextField = ReflectionUtils.findField(JdkSslContext.class, "sslContext");
            ReflectionUtils.makeAccessible(sslContextField);
            SSLContext jdkSslContext = (SSLContext) ReflectionUtils.getField(sslContextField, sslContext);

            httpClient = java.net.http.HttpClient.newBuilder()
                    .version(HttpClient.Version.HTTP_1_1)
                    .connectTimeout(Duration.ofMillis(5000))
                    //.sslContext(jdkSslContext)
                    .build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        jdkHttpClientMonitor.registryHttpClient("default", httpClient);

        RestClient restClient = RestClient.builder()
                .requestFactory(new JdkClientHttpRequestFactory(httpClient))
                .baseUrl(url)
                .messageConverters(messageConverters.getConverters())
                .build();
        return RestClientAdapter.create(restClient);
    }

    @Override
    public HttpExchangeAdapter useApacheHttpClient5(String url) {
        throw new UnsupportedOperationException();
    }

    @Override
    public HttpExchangeAdapter useHttpUrlConnection(String url) {
        throw new UnsupportedOperationException();
    }
}
